package com.fz.service.system.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fz.common.ResponseEntity;
import com.fz.dto.system.area.AreaAdd;
import com.fz.dto.system.area.AreaQuery;
import com.fz.dto.system.area.AreaUpd;
import com.fz.entity.system.Area;
import com.fz.mapper.system.AreaMapper;
import com.fz.service.system.AreaService;
import com.fz.utils.JacksonUtils;
import com.fz.utils.StringUtils;
import com.fz.vo.system.area.AreaTreeVo;
import com.fz.vo.system.area.AreaVo;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : xumj
 * @date : 2021/3/23 10:06
 */
@Service
@SuppressWarnings("unchecked")
@CacheConfig(cacheNames = "area")
public class AreaServiceImpl implements AreaService {

    @Resource
    private AreaMapper areaMapper;

    /**
     * @param pageNum   pageNum
     * @param pageSize  pageSize
     * @param areaQuery areaQuery
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaVo>
     * @description 查询行政区规划码 分页
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    @Cacheable
    public ResponseEntity<AreaVo> findAreaList(Integer pageNum, Integer pageSize, AreaQuery areaQuery) throws Exception{
        Page<AreaVo> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Area> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StringUtils.isNotEmpty(areaQuery.getCode()), Area::getCode, areaQuery.getCode())
                .eq(StringUtils.isNotEmpty(areaQuery.getParentCode()), Area::getParentCode, areaQuery.getParentCode())
                .eq(StringUtils.isNotEmpty(areaQuery.getName()), Area::getName, areaQuery.getName())
                .eq(ObjectUtil.isNotNull(areaQuery.getLevel()), Area::getLevel, areaQuery.getLevel());
        Page<AreaVo> areaVoPage = areaMapper.findAreaList(page, lambdaQueryWrapper);
        return ResponseEntity.buildSuccess(areaVoPage);
    }

    /**
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaTreeVo> 返回树形结构
     * @description 查询行政区规划码
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    @Cacheable(key = "'areaTreeVo'")
    public ResponseEntity<AreaTreeVo> findAreaTree() {
        List<AreaTreeVo> list = areaMapper.selectAll().stream().map(area -> {
            AreaTreeVo vo = new AreaTreeVo();
            vo.setId(area.getId());
            vo.setCode(area.getCode());
            vo.setLevel(area.getLevel());
            vo.setName(area.getName());
            vo.setParentCode(area.getParentCode());
            return vo;
        }).collect(Collectors.toList());
        Map<String, AreaTreeVo> map = new HashMap<>();
        list.forEach(areaTreeVo -> map.put(areaTreeVo.getCode(), areaTreeVo));
        list.clear();
        map.forEach((code, areaTreeVo) -> {
            String parentCode = areaTreeVo.getParentCode();
            if (parentCode == null) {
                list.add(areaTreeVo);
            } else {
                AreaTreeVo parentAreaTreeVo = map.get(parentCode);
                Collection<AreaTreeVo> children = parentAreaTreeVo.getCollection();
                if (children == null) {
                    children = new ArrayList<>();
                    parentAreaTreeVo.setCollection(children);
                }
                children.add(areaTreeVo);
            }
        });
        if (!list.isEmpty()) {
            return ResponseEntity.buildSuccess(list);
        } else {
            return ResponseEntity.buildSuccess(null);
        }
    }

    /**
     * @param areaQuery areaQuery
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaVo>
     * @description 查询新增区规划码列表
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    public ResponseEntity<AreaVo> selectAreasList(AreaQuery areaQuery) {
        LambdaQueryWrapper<Area> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //TODO 查询条件条件添加 ->在此拼接
        lambdaQueryWrapper.eq(StringUtils.isNotEmpty(areaQuery.getCode()), Area::getCode, areaQuery.getCode())
                .eq(StringUtils.isNotEmpty(areaQuery.getParentCode()), Area::getParentCode, areaQuery.getParentCode())
                .eq(StringUtils.isNotEmpty(areaQuery.getName()), Area::getName, areaQuery.getName())
                .eq(ObjectUtil.isNotNull(areaQuery.getLevel()), Area::getLevel, areaQuery.getLevel());
        return ResponseEntity.buildSuccess(areaMapper.selectAreaList(lambdaQueryWrapper));
    }

    /**
     * @param areaAdd     areaAdd
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaVo>
     * @description 新增行政区规划码
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity saveArea(AreaAdd areaAdd) {
        Area area = JacksonUtils.obj2pojo(areaAdd, Area.class);
        areaMapper.insert(area);
        return ResponseEntity.buildSuccess();
    }

    /**
     * @param areaUpd     areaUpd
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaVo>
     * @description 更新行政区规划码
     * @params
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity updateArea(AreaUpd areaUpd) {
        Area area = JacksonUtils.obj2pojo(areaUpd, Area.class);
        areaMapper.updateById(area);
        return ResponseEntity.buildSuccess();
    }

    /**
     * @param ids         ids
     * @return com.fz.common.ResponseEntity<com.fz.vo.system.area.AreaVo>
     * @description 删除行政区规划码
     * @params
     * @author xumj
     * @date 2021/3/26
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity delArea(Integer[] ids) {
        areaMapper.deleteBatchIds(Arrays.asList(ids));
        return ResponseEntity.buildSuccess();
    }
}
